use crate::Document;
use crate::Row;
use crate::{
    row,
    terminalu::{self, Size},
    Terminalu,
};
use core::panic;
use crossterm::{
    cursor::{self, MoveTo},
    event::{
        self, Event, KeyCode, KeyEvent, KeyEventKind, KeyEventState, KeyModifiers, MediaKeyCode,
        ModifierKeyCode,
    },
    terminal, ExecutableCommand, QueueableCommand,
};
use std::env;
use std::{
    fmt::Error,
    io::{self, stdout, Write},
    process::exit,
};
const VERSION: &str = env!("CARGO_PKG_VERSION");
#[derive(Default)]
pub struct Position {
    pub x: usize,
    pub y: usize,
}
pub struct Editor {
    should_quit: bool,
    termialu: Terminalu,
    curor_position: Position,
    offset: Position,
    document: Document,
}

impl Editor {
    /**
     * 初次运行先刷新屏幕
     */
    pub fn run(&mut self) -> std::io::Result<bool> {
        if let Err(e) = self.refresh_screen() {
            self.die(e);
        }
        loop {
            /* if let Err(e)=self.refresh_screen(){
                self.die(e);
            } */

            if event::poll(std::time::Duration::from_millis(50))? {
                match event::read() {
                    Ok(event) => {
                        self.key_trig(event);
                    }
                    Err(e) => {
                        panic!("{}", e);
                    }
                }
            }
        }
    }

    pub fn default() -> Self {
        let argslist: Vec<String> = env::args().collect();
        let document = if argslist.len() > 1 {
            let filename = &argslist[1];
            Document::open(&filename).unwrap_or_default()
        } else {
            Document::default()
        };
        Self {
            should_quit: false,
            termialu: Terminalu::default().expect("Fail to initialize terminal"),
            document,
            curor_position: Position { x: 0, y: 0 },//光标在文件中的位置
            offset: Position::default(),//光标在屏幕中的位置
        }
    }
    /**
     * 程序异常时回调函数
     */
    fn die(&self, e: std::io::Error) {
        Terminalu::clear_screen();
        panic!("{}", e);
    }
    /**
     * 刷新屏幕
     */
    fn refresh_screen(&self) -> Result<(), std::io::Error> {
        Terminalu::cursor_hide();
        // Terminalu::clear_screen();
        Terminalu::cursor_position(&Position { x: 0, y: 0 });

        if self.should_quit {
            Terminalu::clear_screen();
            println!("good bye!!\r");
            exit(1);
        } else {
            self.draw_rows();
            //Terminalu::cursor_position(&self.curor_position);
            Terminalu::cursor_position(&Position {
                x: self.curor_position.x.saturating_sub(self.offset.x),
                y: self.curor_position.y.saturating_sub(self.offset.y),
            });
        }
        Terminalu::show_cursor();
     
        Terminalu::flush()
    }
    /**
     * 处理{欢迎巨}在终端的显示方式
     * 当欢迎句大于终端宽度截断，小于则补space
     */
    fn draw_welcomw_message(&self) {
        let mut welcome_message = format!("hectyo editor -- version{}\r", VERSION);
        let width = self.termialu.size().width as usize;
        let len = welcome_message.len();
        let padding = width.saturating_sub(len) / 2;
        let space = " ".repeat(padding.saturating_sub(1));
        welcome_message = format!("~{}{}", space, welcome_message);
        welcome_message.truncate(width);
        println!("{}\r", welcome_message);
    }
    /**
     *以行为单位渲染终端的显示效果
     *当显示的文档行不为空，则按行显示文本行
     *当显示的文档行为空，则在每行的开头显示~
     *当文档为空，显示欢迎语
     */
    fn draw_rows(&self) {
        let height = self.termialu.size().height;
        for terminal_raw in 0..height - 1 {
            Terminalu::clear_current_line();
            if let Some(row) = self.document.row(terminal_raw as usize + self.offset.y) {
                self.draw_row(row);
            } else if self.document.is_emoty() && terminal_raw == height / 3 {
                self.draw_welcomw_message();
            } else {
                println!("~\r");
            }
        }
    }
   /**
    * 将传入的行数刷新
    */
    pub fn draw_row(&self, row: &Row) {
        let width = self.termialu.size().width as usize;
        let start = self.offset.x;
        let end = self.offset.x + width;
        let row = row.render(start, end);
        println!("{}\r", row)
    }
    /**
     * 处理不同按键按下是对应的操作
     */
    pub fn key_trig(&mut self, key_event: Event) {
        match key_event {
            Event::Key(read_key) => {
                match read_key {
                    KeyEvent {
                        code: KeyCode::Char('c'),
                        modifiers: KeyModifiers::CONTROL,
                        kind: KeyEventKind::Press,
                        state: KeyEventState::NONE,
                    } => {
                        println!("ctrl c press");
                        self.should_quit = true;
                    }
                    KeyEvent {
                        code:
                            KeyCode::Up
                            | KeyCode::Down
                            | KeyCode::Left
                            | KeyCode::Right
                            | KeyCode::PageDown
                            | KeyCode::PageUp
                            | KeyCode::Home
                            | KeyCode::End,
                        modifiers: KeyModifiers::NONE,
                        ..
                    } => {
                        self.move_cursor(read_key);
                    }
                    _ => {
                        println!("key presss");
                        // dbg!(read_key);
                    }
                }
            }
            _ => {
                println!("key event read fail");
            }
        }
        if let Err(e) = self.refresh_screen() {
            self.die(e);
        }
        self.scroll();
    }
    /**
     * 处理光标移动操作
     */
    fn scroll(&mut self) {
        let Position { x, y } = self.curor_position;
        let width = self.termialu.size().width as usize;
        let height = self.termialu.size().height as usize;
        let mut offset = &mut self.offset;
        if y < offset.y {
            offset.y = y;
        } else if y > offset.y.saturating_add(height) {   //当终端中的光标纵坐标大于文件中的坐标时，需要考虑溢出问题
            offset.y = y.saturating_sub(height).saturating_add(1);
        }
        if x < offset.x {
            offset.x = x;
        } else if x >= offset.x.saturating_add(width) {
            offset.x = x.saturating_sub(width).saturating_add(1);
        }
    }
    /**
     * 处理文件中的光标移动
     */
    fn move_cursor(&mut self, key: KeyEvent) {
        let Position { mut y, mut x } = self.curor_position;
        let size = self.termialu.size();
        //let height=size.height.saturating_sub(1) as usize;
        let height = self.document.len();
        // let width=size.width.saturating_sub(1) as usize;
        let mut width = if let Some(row) = self.document.row(y) {
            row.len()
        } else {
            0
        };

        match key.code {
            KeyCode::Up => y = y.saturating_sub(1),
            KeyCode::Down => {
                if y < height {
                    y = y.saturating_add(1);
                }
            }
            KeyCode::Left => x = x.saturating_sub(1),
            KeyCode::Right => {
                if x < width {
                    x = x.saturating_add(1);
                }
            }
            KeyCode::PageDown => y = height,
            KeyCode::PageUp => y = 0,
            KeyCode::Home => x = 0,
            KeyCode::End => x = width,
            _ => (),
        }
        width = if let Some(row) = self.document.row(y) {
            row.len()
        } else {
            0
        };
        if x > width {
            x = width;
        }
        self.curor_position = Position { x, y }
    }
}
